package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.*;
import cn.wolfcode.feign.PayFeignApi;
import cn.wolfcode.feign.UsableIntegralFeignApi;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.PayLogMapper;
import cn.wolfcode.mapper.RefundLogMapper;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.controller.OrderInfoController;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by wolfcode-lanxw
 */
@Service
public class OrderInfoSeviceImpl implements IOrderInfoService {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayLogMapper payLogMapper;
    @Autowired
    private RefundLogMapper refundLogMapper;
    @Autowired
    private PayFeignApi payFeignApi;
    @Autowired
    private UsableIntegralFeignApi usableIntegralFeignApi;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Value(value = "${pay.returnUrl}")
    public String returnUrl;
    @Value(value = "${pay.notifyUrl}")
    public String notifyUrl;

    @Override
    public void saveOrder(OrderInfo orderInfo) {
        orderInfoMapper.insert(orderInfo);
    }

    @Override
    public OrderInfo createOrder(int time, Long seckillId, Long phone) {
        SeckillProductVo seckillProductVo = seckillProductService.find(seckillId + "", time);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateDate(new Date());
        orderInfo.setOrderNo(IdGenerateUtil.get().nextId() + "");
        orderInfo.setUserId(phone);
        orderInfo.setProductId(seckillId);
        orderInfo.setDeliveryAddrId(1L);
        orderInfo.setProductImg(seckillProductVo.getProductImg());
        orderInfo.setProductName(seckillProductVo.getProductName());
        orderInfo.setProductCount(seckillProductVo.getStockCount());
        orderInfo.setProductPrice(seckillProductVo.getProductPrice());
        orderInfo.setSeckillPrice(seckillProductVo.getSeckillPrice());
        orderInfo.setIntergral(seckillProductVo.getIntergral());
        //订单状态
        //支付时间
        //支付方式
        orderInfo.setSeckillDate(seckillProductVo.getStartDate());
        orderInfo.setSeckillTime(seckillProductVo.getTime());
        orderInfo.setSeckillId(seckillProductVo.getId());
        //持久化订单
        saveOrder(orderInfo);
        return orderInfo;

    }

    @Override
    public OrderInfo find(String orderNo) {
        String o = (String)redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_ORDER_HASH.getRealKey(""), orderNo + "");
        if(!StringUtils.isEmpty(o)){
            return JSON.parseObject(o, OrderInfo.class);
        }
        return null;
    }

    @Override
    public int updateCancleStatus(String orderNo, Integer statusTimeout) {
        return orderInfoMapper.updateCancelStatus(orderNo,statusTimeout);
    }

    @Override
    public String payOnline(String orderNo) {
        //给支付流水新增一条信息
        PayLog payLog = new PayLog();
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        if (orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        payLog.setPayType(PayLog.PAY_TYPE_ONLINE);
        payLog.setOutTradeNo(IdGenerateUtil.get().nextId() + "");
        payLog.setTotalAmount(orderInfo.getSeckillPrice()+"");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        payLog.setNotifyTime(sdf.format(new Date()));
        payLog.setTradeNo(orderNo);
        payLogMapper.insert(payLog);

        PayVo payVo = new PayVo();
        payVo.setBody("");
        payVo.setOutTradeNo(orderNo);
        payVo.setTotalAmount(orderInfo.getSeckillPrice()+"");
        payVo.setSubject(orderInfo.getProductName()+orderInfo.getUserId());
        //异步回调地址
        payVo.setNotifyUrl(notifyUrl);
        //同步回调地址
        payVo.setReturnUrl(returnUrl);

        Result<String> stringResult = payFeignApi.payOnline(payVo);
        if (stringResult==null&&stringResult.hasError()){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        return stringResult.getData();
    }

    @Override
    public void changePayStatus(String orderNo,int type) {
        orderInfoMapper.changePayStatus(orderNo,OrderInfo.STATUS_ACCOUNT_PAID,type);
    }



    @Override
    public String payIntegral(String orderNo) {
        PayLog payLog = new PayLog();
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        if (orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        payLog.setPayType(PayLog.PAY_TYPE_INTERGRAL);
        payLog.setOutTradeNo(IdGenerateUtil.get().nextId() + "");
        payLog.setTotalAmount(orderInfo.getIntergral()+"");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        payLog.setNotifyTime(sdf.format(new Date()));
        payLog.setTradeNo(orderNo);
        payLogMapper.insert(payLog);

        OperateIntergralVo operateIntergralVo = new OperateIntergralVo();
        operateIntergralVo.setInfo("");
        operateIntergralVo.setUserId(orderInfo.getUserId());
        operateIntergralVo.setValue(orderInfo.getIntergral());
        operateIntergralVo.setPk(orderNo);
        operateIntergralVo.setValue(orderInfo.getIntergral());
        Result<String> result = usableIntegralFeignApi.payIntergral(operateIntergralVo);
        if (StringUtils.isEmpty(result)){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        orderInfoMapper.changePayStatus(orderNo,OrderInfo.STATUS_ACCOUNT_PAID,PayLog.PAY_TYPE_INTERGRAL);
        return "";
    }


    @Override
    @GlobalTransactional
    public void refund(String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        if (orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        RefundLog refundLog = new RefundLog();
        refundLog.setOutTradeNo(orderNo);
        refundLog.setRefundAmount(orderInfo.getSeckillPrice()+"");
        refundLog.setRefundReason("不想要了");
        refundLog.setRefundType(PayLog.PAY_TYPE_ONLINE);
        refundLog.setRefundTime(new Date());
        refundLogMapper.insert(refundLog);

        RefundVo refundVo = new RefundVo();
        refundVo.setOutTradeNo(orderNo);
        refundVo.setRefundAmount(orderInfo.getSeckillPrice()+"");
        refundVo.setRefundReason("不想要了");

        Result<Boolean> result = payFeignApi.refund(refundVo);
        if (result==null&&result.hasError()){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        if (!result.getData()){
            throw new BusinessException(SeckillCodeMsg.REFUND_ERROR);
        }

        orderInfoMapper.changeRefundStatus(orderNo,OrderInfo.STATUS_REFUND);

        //回补真实库存

        seckillProductService.incrCount(orderInfo.getSeckillId());
        //回补预库存
        int count = seckillProductService.getStockCount(orderInfo.getSeckillId());
        redisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(orderInfo.getSeckillTime() + ""),
                orderInfo.getSeckillId()+"",
                count);

        //修改本地标识
        rocketMQTemplate.syncSend(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC,orderInfo.getSeckillId());
    }

    @Override
    @GlobalTransactional
    public void refundIntegral(String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        if (orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        //退款流水
        RefundLog refundLog = new RefundLog();
        refundLog.setOutTradeNo(orderNo);
        refundLog.setRefundAmount(orderInfo.getIntergral()+"");
        refundLog.setRefundReason("舍不得我的积分");
        refundLog.setRefundType(PayLog.PAY_TYPE_INTERGRAL);
        refundLog.setRefundTime(new Date());
        refundLogMapper.insert(refundLog);
        //回退积分
        OperateIntergralVo operateIntergralVo = new OperateIntergralVo();
        operateIntergralVo.setValue(orderInfo.getIntergral());
        operateIntergralVo.setPk(orderNo);
        operateIntergralVo.setUserId(orderInfo.getUserId());
        operateIntergralVo.setInfo("舍不得我的积分");
        usableIntegralFeignApi.refundIntegral(operateIntergralVo);

        orderInfoMapper.changeRefundStatus(orderNo,OrderInfo.STATUS_REFUND);

        //回补真实库存
        seckillProductService.incrCount(orderInfo.getSeckillId());
        //回补预库存
        int count = seckillProductService.getStockCount(orderInfo.getSeckillId());
        redisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(orderInfo.getSeckillTime() + ""),
                orderInfo.getSeckillId()+"",
                count+"");

        //修改本地标识
        rocketMQTemplate.syncSend(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC,orderInfo.getSeckillId());

    }
}
